<template>
  <div>
    <VAvatar
      color="success"
      icon="tabler-brand-openai"
      style="margin-inline-end:8px"
    />

    <span style=" position: relative; inset-block-start: -15px;margin-inline-start: 15px"
      ><b>ChatGPT</b></span
    >
    <div
      class="mb-4 flex rounded-xl px-2 py-6 dark:bg-slate-900 sm:px-4"
      style=" margin-block-start: -30px;padding-block-start: 0"
    >
      <div class="flex max-w-3xl items-center rounded-xl">
        <p>
          <v-md-preview :text="msgMarkdown"></v-md-preview>

          <!-- <span v-for="response in msgHtml" :key="response.id"> -->
          <!-- <span v-if="response.type == 'str'" v-html="response.content"></span> -->
          <!-- </span> -->
        </p>
      </div>
    </div>
  </div>
</template>

<script setup>
import { onMounted, ref } from "vue";

const props = defineProps({
  record: {
    type: Object,
    required: true,
  },
});

const record = ref(props.record);

onMounted(() => {
  callStreamEndpoint5();
});

const msgHtml = ref([]);
const msgMarkdown = ref("");

const closeEventSource = (eventSource) => {
  eventSource.close();
  // console.log(msgHtml)
};

const callStreamEndpoint5 = () => {
  const msg = record.value.msg;
  const eventSource = new EventSource(
    "http://127.0.0.1:8090/chat/stream/generate?message=" + msg
  );

  let isInCodeBlock = false; // 用于跟踪是否在代码块内
  let tempMsg = ""; // 用于暂存截取的内容

  // 处理服务器发送的消息
  eventSource.onmessage = (event) => {
    const chatResponse = JSON.parse(event.data);
    // 如果数据中包含了 "STOP" 状态，关闭 EventSource 连接
    if (chatResponse.result.metadata.finishReason === "STOP") {
      closeEventSource(eventSource);
      return;
    }

    const content = chatResponse.result.output.content;
    msgMarkdown.value += content;

    // 将收到的内容逐字符处理
    for (let i = 0; i < content.length; i++) {
      if (!isInCodeBlock) {
        // 如果不在代码块内
        if (content[i] === "`") {
          // 如果遇到 ` 符号，表示开始代码块
          isInCodeBlock = true;
          if (tempMsg.length > 0) {
            // 如果 tempMsg 不为空，表示已经截取到内容，将其作为普通字符串存入数组中
            appendOrPush("str", tempMsg);
            tempMsg = ""; // 重置 tempMsg
          }
        } else {
          // 否则，将字符作为普通字符串存入数组中
          if (content[i] === "\n") {
            // 如果遇到换行符，则将当前内容作为新的对象推送到数组中
            appendOrPush("str", tempMsg);
            tempMsg = ""; // 重置 tempMsg
          } else {
            tempMsg += content[i];
          }
        }
      } else {
        // 如果在代码块内
        if (content[i] === "`") {
          // 如果遇到 ` 符号，表示结束代码块
          isInCodeBlock = false;
          // 将截取到的内容作为代码块存入数组中
          appendOrPush("code", tempMsg);
          tempMsg = ""; // 重置 tempMsg
        } else {
          // 否则，将字符作为代码块内容存入 tempMsg 中
          tempMsg += content[i];
        }
      }
    }
    // 处理最后的剩余内容
    if (tempMsg.length > 0) {
      appendOrPush(isInCodeBlock ? "code" : "str", tempMsg);
      tempMsg = ""; // 重置 tempMsg
    }
  };

  // 处理连接错误
  eventSource.onerror = (error) => {
    console.error("EventSource failed:", error);
    eventSource.close();
  };

  // 辅助函数：根据当前的类型追加或推送到 msgHtml 数组中
  function appendOrPush(type, content) {
    if (type === "code") {
      console.log(content);
    }
    if (type === "str" && content.includes("\n")) {
      // 如果是普通字符串且包含换行符，则将当前内容作为新的对象推送到数组中
      msgHtml.value.push({ type, content });
    } else if (
      msgHtml.value.length > 0 &&
      msgHtml.value[msgHtml.value.length - 1].type === type
    ) {
      // 否则，根据当前的类型追加或推送到数组中
      msgHtml.value[msgHtml.value.length - 1].content += content;
    } else {
      msgHtml.value.push({ type, content });
    }
  }
};
</script>
